// PR debug/52048
// { dg-do compile }
// { dg-options "-fcompare-debug -fnon-call-exceptions -fno-tree-dominator-opts -O2 -Wno-return-type" }

template <typename T> struct A;
template <typename T>
struct A <T *>
{
  typedef T &a;
};
template <typename T>
struct B
{
  typedef typename A <T>::a a;
  a operator *() {}
};
template <typename T, typename U>
bool operator != (B <T>, B <U>)
{
}
template <typename T>
struct C
{
  typedef T *c;
  template <typename>
  struct D { typedef C d; };
};
template <typename T, typename U> struct E
{
  typedef typename U::template D <T>::d e;
};
template <typename T, typename U = C <T> >
struct F
{
  typedef E <T, U> b;
  typedef typename b::e e;
  typedef typename e::c c;
  typedef B <c> i;
  i begin ();
  i end ();
};
class G;
class H;
struct I
{
  void *i;
  template <typename T> T foo ();
};
struct J : public I
{
  virtual bool bar ();
};
class K {};
struct L
{
  bool baz () {}
};
struct M
{
  K m1 (K);
  K m2 (H *) {}
};
struct N : J
{
  bool bar (G &);
};
bool
N::bar (G &)
{
  M m = foo <M> ();
  F <H *> f;
  for (F <H *>::i I = f.begin (), E = f.end (); I != E;)
    {
      H *h = *I;
      L l;
      if (l.baz ())
	m.m1 (m.m2 (h));
    }
}
